<?php

declare(strict_types=1);

namespace App\Library\Task\library\queue\drivers\mns;

use App\Constants\ErrorCode;
use App\Exception\AppException;
use function App\Helpers\mb_unserialize;
use App\Library\Log\Log;
use App\Library\Task\library\queue\drivers\DriverServerImp;

class QueueServerMns implements DriverServerImp
{

    private $_queuedb;
    private $retryCount = 1;
    private $maxRetryCount = 5;

    public function __construct()
    {
        $this->_queuedb = new QueueDBMns();
    }

    /**
     * @param \App\Library\Task\library\queue\drivers\unknown $key
     * @param \App\Library\Task\library\queue\drivers\监听时间 $time
     * @param bool $is_del
     * @return bool|mixed|string
     * 取出队列
     */
    public function pop($key, $time, $is_del = true)
    {
        try {
            $messageBody = $this->_queuedb->pop($key, $time);
            if (empty($messageBody)) {
                return false;
            }

            // 是否删除队列消息
            if ($is_del) {
                $this->deleteMsg($key);
            }

            return unserialize($messageBody);

//            return mb_unserialize($messageBody);
        } catch (\Exception $exception) {
            Log::fatal($exception,'mns队列 pop错误');
            return '';
        }

    }

    /**
     * Notes 手动删除
     * @param $key
     * @return bool
     */
    public function delMsg($key)
    {
        return $this->deleteMsg($key);
    }

    private function deleteMsg($key)
    {
        $result = $this->_queuedb->delete($key);
        if ($result['state'] === false) {
            $mnsError = $result['msg'];
            //判断错误消息需不需要进行重试
            $errorMsgRetry = false;
            if ($mnsError->getMnsErrorCode() == 'ServerError') {
                $errorMsgRetry = true;
            } elseif (strpos($mnsError->getMessage(), 'cURL error 28: Operation timed out') !== false) {
                $errorMsgRetry = true;
            }
            if ($errorMsgRetry && $this->retryCount <= $this->maxRetryCount) {
                //进行重试
                Log::warning(new AppException(ErrorCode::OTHER_ERR,'mns队列 delete异常：' . sprintf('%s', $mnsError) . '; 第' . $this->retryCount . '次重试' . '; trace:' . json_encode($mnsError->getTrace())));
                $this->retryCount += 1;
                return $this->deleteMsg($key);
            } else {
                //不需要重试的或者重试完成还是报错的错误直接记录并报警
                Log::fatal(new AppException(ErrorCode::OTHER_ERR, 'mns队列 delete异常：' . sprintf('%s', $mnsError) . '; trace:' . json_encode($mnsError->getTrace())));
            }
        }
        //重试次数重置为1
        $this->retryCount = 1;
        return $result['state'];
    }

    public function scan($driver = 'default')
    {
        try {
            return $this->_queuedb->scan($driver);
        } catch (\Exception $exception) {
            Log::fatal(new AppException(ErrorCode::OTHER_ERR, 'mns队列 pop错误'));
            return '';
        }

    }

    public function clear($driver = 'default')
    {
        try {
            return $this->_queuedb->clear($driver);
        } catch (\Exception $exception) {
            Log::fatal(new AppException(ErrorCode::OTHER_ERR, 'mns队列 pop错误'));
            return false;
        }
    }

}